package com.mantru.iotpot.job;

import android.media.MediaPlayer;

import com.mantru.iotpot.ApplicationClass;
import com.mantru.iotpot.R;
import com.mantru.iotpot.modbus.Common;

import org.json.JSONArray;
import org.json.JSONObject;

import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
 * 立即炒制管理器
 */
public class CookingMaster {
    private ApplicationClass ac;
    //步骤队列，key是从1开始的
    public Map<Integer, CookingDetail> steep_map;
    //UI界面上的几个参数值
    //执行状态，0未执行、1执行中、2已完成、3终止了
    public int steep_status;
    //当前执行的集合id，从1开始
    public int steep_index;
    //机械爪转速，0-5档
    public int gripper_speed_value;
    //总时长(秒)、已执行的时间(秒)、剩余时间（秒）
    public long total_time = 0, pass_time = 0, remain_time = 0;
    //播mp3的对象
    private MediaPlayer mp1, mp2;
    //区别自动炒菜和洗锅，1自动炒菜、2洗锅、3养锅
    private int cooking_type = 1;

    //创建
    public CookingMaster(ApplicationClass ac, JSONObject spec_object, int cooking_type){
        this.ac = ac;
        this.steep_status = 0;  //未执行
        this.gripper_speed_value = 0;
        this.cooking_type = cooking_type;
        ac.gripper_speed_value = 0;
        ac.gripper_rotation_value = 0;
        try {
            this.total_time = spec_object.getInt("end_time");
            this.pass_time = 0;
            this.remain_time = this.total_time - this.pass_time;
            JSONArray steep_data = spec_object.getJSONArray("steep_data");
            //对步骤里的开始时间进行自然排序
            List<Map.Entry<Integer, JSONObject>> tree_map = new ArrayList<>();
            for (int i=0; i<steep_data.length(); i++)
                tree_map.add(new AbstractMap.SimpleEntry<>(steep_data.getJSONObject(i).getInt("time_long"), steep_data.getJSONObject(i)));
            //排序
            tree_map.sort(Comparator.comparing(Map.Entry::getKey));
            //将相同开始时间的步骤归入同一步骤
            int steep_index = 1, time_value_old = -1, id = 0;
            steep_map = new HashMap<>();
            for (Map.Entry<Integer, JSONObject> entry : tree_map) {
                id++;
                CookingDetail detail_ent;
                CookingSteep steep_ent = new CookingSteep(ac, entry.getValue(), steep_index, id);
                if (time_value_old == -1 || steep_ent.time_long == time_value_old) {
                    if (steep_map.containsKey(steep_index))
                        detail_ent = steep_map.get(steep_index);
                    else {
                        detail_ent = new CookingDetail(steep_index);
                        steep_map.put(steep_index, detail_ent);
                        time_value_old = steep_ent.time_long;
                    }
                }else {
                    steep_index++;
                    detail_ent = new CookingDetail(steep_index);
                    steep_map.put(steep_index, detail_ent);
                    time_value_old = steep_ent.time_long;
                }
                detail_ent.AddSteep(steep_ent);
            }
            //再遍历一遍，设置每个集合的总时长
            if (steep_map.size() == 1) {
                ac.SaveLog("CookingMaster----1111,this.total_time=" + this.total_time);
                CookingDetail detail_ent1 = steep_map.get(1);
                ac.SaveLog("CookingMaster----2222");
                detail_ent1.total_time = this.total_time;
                ac.SaveLog("CookingMaster----3333");
            } else {
                for (int i = 2; i <= steep_map.size(); i++) {
                    CookingDetail detail_ent1 = steep_map.get(i - 1);
                    CookingDetail detail_ent2 = steep_map.get(i);
                    //ac.SaveLog("i="+i+",detail_ent1.time_long=" + detail_ent1.time_long + ",detail_ent2.time_long=" + detail_ent2.time_long);
                    detail_ent1.total_time = detail_ent2.time_long - detail_ent1.time_long;
                    if (i == steep_map.size())
                        detail_ent2.total_time = this.total_time - detail_ent2.time_long;

                }
            }
            //要判断机械臂在放下位
            //要判断锅处于原位
            //要判断料盒轨处于第1位
            if (ac.gripper_position_value != 1 || ac.pot_position_value != 3 || ac.box_position_value != 1) {
                ac.Cooking_Setting3Position("jobmaster");
                return;
            }

            //启动
            Start();

        } catch (Exception ex) {
            ac.SaveLog("CookingMaster初始化出错：" + ex.getMessage());
        }
    }

    //启动
    public void Start() {
        if (this.steep_status != 0)
            return;
        this.steep_status = 1;  //执行中
        this.steep_index = 1;   //集合序号从1开始
        if (steep_map.containsKey(this.steep_index)) {
            CookingDetail detail_ent = steep_map.get(this.steep_index);
            detail_ent.steep_status = 1;  //执行中
            SendDetail(detail_ent);       //发送指令
        }
        //启动计时
        StartTimer();
        //播放  开始烹饪.mp3
        PlayMp3(1);
    }

    //停止
    public void Stop() {
        //先停计时线程
        timer_is_open = false;
        steep_status = 3;  //终止了
        //火力0档、机构臂抬起、喷泵全关
        Close(1);
    }

    //立即停止
    public void Stop_Quickly(){
        //先停计时线程
        timer_is_open = false;
        steep_status = 3;  //终止了
        //火力0档、机构臂抬起、喷泵全关
        Close(2);
    }

    //火力0档、机构臂抬起、喷泵全关
    //type=1普通停止、2立即停止
    private void Close(int type) {
        try {
            //自动炒菜
            if (cooking_type == 1) {
                if (type == 1) {
                    //机械爪，1档
                    ac.com.writeSingleRegister(0x01, 0x00E1, 0x01, null);
                } else {
                    //机械爪，0档
                    ac.com.writeSingleRegister(0x01, 0x00E1, 0x00, null);
                }
                //料盒不用动它
                //ac.com.writeSingleRegister(0x01, 0x00DE, 0x01, null);
            } else {
                //机械爪，0档
                ac.com.writeSingleRegister(0x01, 0x00E1, 0x00, null);
                //料盒拉回去1位
                ac.com.writeSingleRegister(0x01, 0x00DE, 0x01, null);
            }
            //火力，0档
            ac.com.writeSingleRegister(0x01, 0x00FD, 0x00, null);
            //机构臂抬起
            //ac.com.writeSingleRegister(0x01, 0x00DF, 0x02, null);
            //喷泵全关
            int[] nozzle_values = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
            ac.com.writeHoldingRegisters(0x01, 0x00F2, nozzle_values.length, nozzle_values);
            nozzle_values = null;

            //播放
            PlayMp3(2);
            ac.SaveLog("CookingMaster.Close()了");
        } catch (Exception ex) {
            ac.SaveLog("CookingMaster.Close()出错：" + ex.getMessage());
        }
    }

    //将集合里的全部指令发送到队列
    private void SendDetail(CookingDetail ent) {
        ac.SaveLog("CookingMaster.SendDetail()执行steep_id=" + ent.steep_index + ",steep_name=" + ent.steep_name + ",time_long=" + ent.time_long);
        try {
            for (int i=0; i<ent.list.size(); i++) {
                CookingSteep steep = ent.list.get(i);
                //1锅设置、4手动投放
                if (steep.steep_type == 1) {
                    //火力，0-9档
                    ac.com.writeSingleRegister(0x01, 0x00FD, steep.fire_value, null);
                    //机械臂设置
                    ac.GripperSetting(steep.gripper_position_value, steep.gripper_rotation_value, steep.gripper_speed_value);
                }
                //2调味料投放
                if (steep.steep_type == 2){
                    int[] nozzle_values = new int[11];
                    nozzle_values[0] = Common.NozzleControl(steep.nozzle1_value, 1);
                    nozzle_values[1] = Common.NozzleControl(steep.nozzle2_value, 2);
                    nozzle_values[2] = Common.NozzleControl(steep.nozzle3_value, 3);
                    nozzle_values[3] = Common.NozzleControl(steep.nozzle4_value, 4);
                    nozzle_values[4] = Common.NozzleControl(steep.nozzle5_value, 5);
                    nozzle_values[5] = Common.NozzleControl(steep.nozzle6_value, 6);
                    nozzle_values[6] = Common.NozzleControl(steep.nozzle7_value, 7);
                    nozzle_values[7] = Common.NozzleControl(steep.nozzle8_value, 8);
                    nozzle_values[8] = Common.NozzleControl(steep.nozzle9_value, 9);
                    nozzle_values[9] = Common.NozzleControl(steep.nozzle10_value, 10);
                    nozzle_values[10] = Common.NozzleControl(steep.nozzle11_value, 11);
                    //ac.com.writeHoldingRegisters(0x01, 0x00F2, nozzle_values.length, nozzle_values);
                    for (int j=0; j<nozzle_values.length; j++) {
                        if (nozzle_values[j] > 0)
                            ac.com.writeSingleRegister(0x01, Common.nozzle_address_list[j + 1], nozzle_values[j], null);
                    }
                    nozzle_values = null;
                }
                //3料盒投放
                if (steep.steep_type == 3) {
                    int box_index = 1;
                    if (steep.box2_value > 0) box_index = 2;
                    if (steep.box3_value > 0) box_index = 3;
                    if (steep.box4_value > 0) box_index = 4;
                    ac.Cooking_SettingBoxPosition(box_index, steep.box_release_type);
                }


            }
        } catch (Exception ex) {
            ac.SaveLog("CookingMaster.SendDetail("+ent.steep_index+","+ent.steep_name+")出错：" + ex.getMessage());
        }
    }


    //定时器触发事件，1秒触发1次
    private void OnTimer(){
        try {
            //已执行时间+1秒
            pass_time++;
            remain_time = total_time - pass_time;
            if (remain_time < 0)
                remain_time = 0;
            //集合执行时间+1秒
            if (steep_map.containsKey(steep_index)) {
                CookingDetail detail_ent = steep_map.get(steep_index);
                detail_ent.pass_time++;
                if (detail_ent.pass_time >= detail_ent.total_time) {
                    detail_ent.steep_status = 2;      //已完成
                    if (steep_index < steep_map.size()) {
                        //取下一步
                        steep_index++;
                        detail_ent = steep_map.get(steep_index);
                        detail_ent.steep_status = 1;  //执行中
                        SendDetail(detail_ent);       //发送指令
                    } else {
                        //全部集合执行完了
                        steep_status = 2;             //已完成
                        timer_is_open = false;        //结束定时器线程
                        //关停火力等
                        Close(1);
                    }
                }
            }
        } catch (Exception ex) {
            ac.SaveLog("CookingMaster.OnTimer()出错：" + ex.getMessage());
        }
    }


    //启动计时器线程
    private boolean timer_is_open;
    private void StartTimer()
    {
        timer_is_open = true;
        new Thread() {
            @Override
            public void run() {
                while (timer_is_open) {
                    try {
                        Thread.sleep(1000);
                        OnTimer();
                    } catch (Exception ex) {
                    }
                }
                //SaveLog("StartTimer(),end,timer_is_open=" + timer_is_open);
            }
        }.start();
    }

    //获取json，用于显示步骤列表
    public String getJsonString()
    {
        String json_data = "";
        for (int i=1; i<=steep_map.size(); i++)
        {
            CookingDetail ent = steep_map.get(i);
            long remain_time = ent.total_time - ent.pass_time;
            if (remain_time < 0)
                remain_time = 0;
            String sub_data = "{\"steep_index\":" + ent.steep_index
                    + ",\"steep_name\":\"" + ent.steep_name + "\""
                    + ",\"steep_status\":" + ent.steep_status
                    + ",\"remain_time\":" + remain_time + ""
                    + ",\"total_time\":" + ent.total_time + "}";
            if (json_data.length() > 0)
                json_data += ",";
            json_data += sub_data;
        }
        json_data = "{\"data\":[" + json_data + "]}";
        return json_data;
    }

    //获取json，用于显示步骤图
    public String getJsonString_Steep()
    {
        String json_data = "";
        for (int i=1; i<=steep_map.size(); i++)
        {
            CookingDetail ent = steep_map.get(i);
            long remain_time = ent.total_time - ent.pass_time;
            if (remain_time < 0)
                remain_time = 0;
            String sub_data = "{\"steep_index\":" + ent.steep_index
                    + ",\"steep_name\":\"" + ent.steep_name + "\""
                    + ",\"steep_status\":" + ent.steep_status
                    + ",\"remain_time\":" + remain_time + ""
                    + ",\"total_time\":" + ent.total_time + "";
            //读取步骤里的子项
            String data2 = "\"时间："+ent.total_time+"秒\"";
            for (int j=0; j<ent.list.size(); j++) {
                CookingSteep ent2 = ent.list.get(j);
                data2 += ent2.steep_show_data;
            }
            sub_data += ",\"data\":[" + data2 + "]}";

            if (json_data.length() > 0)
                json_data += ",";
            json_data += sub_data;
        }
        json_data = "{\"data\":[" + json_data + "]}";
        return json_data;
    }

    //播放  1--开始烹饪.mp3  2--结束烹饪.mp3
    private void PlayMp3(int file_id){
        if (cooking_type != 1)
            return;
        try {
            if (file_id == 1) {
                if (mp2 != null) {
                    mp2.release();
                    mp2 = null;
                }
                mp1 = MediaPlayer.create(ac, R.raw.start_cook);
                mp1.start();
            }
            if (file_id == 2) {
                if (mp1 != null) {
                    mp1.release();
                    mp1 = null;
                }
                mp2 = MediaPlayer.create(ac, R.raw.end_cook);
                mp2.start();
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}


